﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NcfDB.Model
{
    class Database
    {
        //Configuration
        public const int dbNameBytesLimit = 200;
        public const string metaDataFileExtension = ".dbf";
        public const string dataFileExtension = ".dat";

        //Properties
        protected string dbName;
        protected Dictionary<string,Table> tables;
        public string Name { get { return this.dbName; } set { this.dbName = Name; } }
        public Dictionary<string, Table>.ValueCollection Tables { get { return this.tables.Values; } }

        public Database()
        {
            this.tables = new Dictionary<string, Table>();
        }
        public void setDbName(string name)
        {
            this.dbName = name;
        }
        public Table getTable(string name)
        {
            return this.tables[name];
        }
        public List<string> getAllTableName()
        {
            List<string> names = new List<string>();
            foreach (var table in this.tables)
                names.Add(table.Key);
            return names;
        }
        public void addTable(Table table)
        {
            if (!this.tables.ContainsKey(table.Name))
                this.tables.Add(table.Name, table);
        }
        public void deleteTable(string tableName)
        {
            if (this.tables.ContainsKey(tableName))
                this.tables.Remove(tableName);
        }
        public string getFilePath(bool isDbf)
        {
            if (isDbf)
                return CoreDBSystem.diskFilePathPrefix + this.Name + Database.metaDataFileExtension;
            else
                return CoreDBSystem.diskFilePathPrefix + this.Name + Database.dataFileExtension;
        }
        public static string getFilePath(string dbName, bool isDbf)
        {
            if (isDbf)
                return CoreDBSystem.diskFilePathPrefix + dbName + Database.metaDataFileExtension;
            else
                return CoreDBSystem.diskFilePathPrefix + dbName + Database.dataFileExtension;
        }
        public static Database readFromStream(string dbName)
        {
            FileStream dbfFs = new FileStream(Database.getFilePath(dbName, true), FileMode.Open, FileAccess.Read);
            FileStream datFs = new FileStream(Database.getFilePath(dbName, false), FileMode.Open, FileAccess.Read);
            StreamReader dbfSr = new StreamReader(dbfFs);
            StreamReader datSr = new StreamReader(datFs);
            Database database = new Database();
            database.dbName = dbName;
            database.tables = new Dictionary<string, Table>();
            Table table = new Table();
            table = Table.readFromStream(ref dbfFs,ref datFs, ref dbfSr,ref datSr);
            while(table != null)
            {
                database.tables.Add(table.Name, table);
                table = Table.readFromStream(ref dbfFs,ref datFs, ref dbfSr,ref datSr);
            }
            dbfFs.Close();
            datFs.Close();
            dbfSr.Close();
            datSr.Close();
            return database;
        }

        public void save()
        {
            FileStream dbfFs = new FileStream(this.getFilePath(true), FileMode.Create, FileAccess.ReadWrite);
            FileStream datFs = new FileStream(this.getFilePath(false), FileMode.Create, FileAccess.ReadWrite);
            foreach (Table table in this.tables.Values)
            {
                table.saveField(ref dbfFs);
                table.saveRow(ref datFs);
            }
            dbfFs.Flush();
            datFs.Flush();
            dbfFs.Close();
            datFs.Close();
        }
    }
}
